﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace JeanFish
{
    /// <summary>
    /// A helper containing extension methods for collection.
    /// </summary>
    public static class CollectionHelper
    {
        /// <summary>
        /// Create an iterator for the specified enumerable collection sliced with a given size.
        /// </summary>
        /// <typeparam name="TSource">The type of the element of source</typeparam>
        /// <param name="source">An enumerable collection to return element from</param>
        /// <param name="eachSize">The size of each slice</param>
        /// <param name="startIndex">The index where the subsquence of the collection to slice begins; Default value is 0</param>
        /// <param name="endIndex">The index where the subsquence of the collcetion to slice ends; Default value is null, indicating the end of the collection</param>
        /// <returns>Each slice collection; For compatibility, use IQueryable interface</returns>
        public static IEnumerable<IQueryable<TSource>> Each<TSource>(this IEnumerable<TSource> source, int eachSize, int startIndex = 0,int? endIndex=null)
        {
            if (source == null)
                throw new ArgumentNullException("source");
            if (eachSize <= 0)
                throw new ArgumentOutOfRangeException("size");
            if (startIndex < 0)
                throw new ArgumentOutOfRangeException("startIndex");
            int end = endIndex ?? int.MaxValue;
            if (end < 0 || end < startIndex)
                throw new ArgumentOutOfRangeException("endIndex");
            IQueryable<TSource> remaining = source.AsQueryable().Skip(startIndex);
            int cursor = startIndex;
            while (remaining.Any())
            {
                cursor += eachSize;
                if (cursor > endIndex)
                    eachSize = endIndex.Value - (cursor - eachSize)+1;
                yield return remaining.Take(eachSize);
                if (cursor > endIndex) break;
                remaining = remaining.Skip(eachSize);
            }
        }
        /// <summary>
        /// Wrap the given element into a List.
        /// </summary>
        /// <typeparam name="T">The type of the element to wrap</typeparam>
        /// <param name="object">The element to wrap</param>
        /// <returns>A list containing the given element</returns>
        public static List<T> ToList<T>(this T @object)
        {
            return new List<T>() { @object };
        }
    }
}